home *** CD-ROM | disk | FTP | other *** search
- /*
- Component.c
-
- Sample code for a simple component. It really does nothing, but it can be used as a spring-board
- for building other components.
- */
-
- #if defined(powerc) || defined(__powerc)
- #include <stdlib.h>
- #endif
-
- #include <Components.h>
- #include <Errors.h>
- #include <Packages.h>
- #include <Folders.h>
- #include <Notification.h>
-
- #include "syslog internals.h"
- #include "syslog component.h"
-
- #include "ShowInitIcon.h"
- #include "libsprintf.h"
-
- /*
- kIconID is the constant specifying which icon to display at system startup. This allows for different
- icons to be displayed depending on the code which is executing.
- */
- #if defined(powerc) || defined (__powerc)
- #define kIconID 140
- #else
- #define kIconID 141
- #endif
-
- /*
- kMaxIdentLen is a constant which represents the maximum size an ident string will be. The total
- max is 100. By controling the size of the ident string, we ensure that there will be enough room in
- a Str255 string for the ident string, time and date, priority, and message.
- */
- #define kMaxIdentLen 60
-
- /*
- kSyslogCreator is the creator type used when creating log files. Use your favorite text editor here.
- */
- #define kSyslogCreator 'SPM '
-
- pascal ComponentResult ComponentOpen(Handle storage,ComponentInstance self);
- pascal ComponentResult ComponentClose(Handle storage,ComponentInstance self);
- pascal ComponentResult ComponentCanDo(short selector);
- pascal ComponentResult ComponentVersion(void);
- pascal ComponentResult ComponentTarget(Handle storage,ComponentInstance self);
-
- pascal ComponentResult ComponentRegister(Handle storage);
-
- pascal ComponentResult ComponentOpenlog(Handle storage,const char* ident,long logopt,short facility);
- pascal ComponentResult ComponentSyslog(Handle storage,short priority,const char* message);
- pascal ComponentResult ComponentCloselog(Handle storage);
- pascal ComponentResult ComponentSetlogmask(Handle storage,short maskpri);
- pascal ComponentResult ComponentSetFile(Handle storage,FSSpecPtr spec);
-
- pascal ComponentResult ComponentGetError(Handle storage,OSErr* err);
-
- // some string routines so we don't need to include ANSI libs
- static short Strlen(char* s){
- register char* cp=s;
- register short sh=0;
-
- if (s==(char*)0)
- return 0;
-
- while (*cp){
- sh++;
- cp++;
- }
-
- return sh;
- }
-
- static void Strncpy(char* s1,char* s2,short num){
-
- // copy the strings
- BlockMoveData((Ptr)s2,(Ptr)s1,num);
-
- // terminate the new string
- s1[num]=0;
- }
-
- static void Strcpy(char* s1,char* s2){
- // Call strncpy with the string's length
- Strncpy(s1,s2,Strlen(s2));
- }
-
- static void ConcatPString(StringPtr a,StringPtr b);
- static void ConcatPString(StringPtr a,StringPtr b){
- register unsigned char* ap;
- register unsigned char* bp;
- register unsigned char c;
-
- ap=&(a[a[0]+1]);
- bp=b;bp++;
- c=b[0];
-
- while (c){
- *ap=*bp;
- ap++;
- bp++;
- c--;
- }
-
- (a[0])+=b[0];
- }
-
- pascal ComponentResult main(ComponentParameters* params,Handle storage){
- ComponentResult res=((ComponentResult)noErr);
- long lval;
- ComponentFunctionUPP cfupp;
-
- #if defined(powerc) || defined(__powerc)
- __rsrcinit();
- #endif
-
- switch(params->what){
- // Component Manager Routines
- case kComponentOpenSelect:
- cfupp=(ComponentFunctionUPP)NewComponentWithStorageProc(ComponentOpen);
- res=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentWithStorageProc(cfupp);
- break;
- case kComponentCloseSelect:
- cfupp=(ComponentFunctionUPP)NewComponentWithStorageProc(ComponentClose);
- res=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentWithStorageProc(cfupp);
- break;
- case kComponentCanDoSelect:
- cfupp=(ComponentFunctionUPP)NewComponentShortProc(ComponentCanDo);
- res=CallComponentFunction(params,cfupp);
- DisposeComponentShortProc(cfupp);
- break;
- case kComponentVersionSelect:
- cfupp=(ComponentFunctionUPP)NewComponentVoidProc(ComponentVersion);
- res=CallComponentFunction(params,cfupp);
- DisposeComponentVoidProc(cfupp);
- break;
- case kComponentTargetSelect:
- cfupp=(ComponentFunctionUPP)NewComponentWithStorageProc(ComponentTarget);
- res=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentWithStorageProc(cfupp);
- break;
- case kComponentRegisterSelect:
- cfupp=(ComponentFunctionUPP)NewComponentHandleProc(ComponentRegister);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentHandleProc(cfupp);
- res=(ComponentResult)lval;
- break;
-
- // Component Specific Routines
-
- case kopenlogSelector:
- cfupp=(ComponentFunctionUPP)NewComponentOpenlogProc(ComponentOpenlog);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentOpenlogProc(cfupp);
- res=(ComponentResult)lval;
- break;
- case ksyslogSelector:
- cfupp=(ComponentFunctionUPP)NewComponentSyslogProc(ComponentSyslog);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentSyslogProc(cfupp);
- res=(ComponentResult)lval;
- break;
- case kcloselogSelector:
- cfupp=(ComponentFunctionUPP)NewComponentHandleProc(ComponentCloselog);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentHandleProc(cfupp);
- res=(ComponentResult)lval;
- break;
- case ksetlogmaskSelector:
- cfupp=(ComponentFunctionUPP)NewComponentSetlogmaskProc(ComponentSetlogmask);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentSetlogmaskProc(cfupp);
- res=(ComponentResult)lval;
- break;
- case kSetFileSelector:
- cfupp=(ComponentFunctionUPP)NewComponentSetFileProc(ComponentSetFile);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentSetFileProc(cfupp);
- res=(ComponentResult)lval;
- break;
- case kGetErrorSelector:
- cfupp=(ComponentFunctionUPP)NewComponentOSErrPtrProc(ComponentGetError);
- lval=CallComponentFunctionWithStorage(storage,params,cfupp);
- DisposeComponentOSErrPtrProc(cfupp);
- res=(ComponentResult)lval;
- break;
-
- default:
- res=badComponentSelector;
- break;
- }
-
- #if defined(powerc) || defined(__powerc)
- __rsrcterm();
- #endif
-
- return res;
- }
-
- pascal ComponentResult ComponentOpen(Handle storage,ComponentInstance self){
- ComponentStorageHdl sto;
- ComponentResult res=((ComponentResult)noErr);
- OSErr anErr=noErr;
- short vref;
- long dirid;
- Handle i0h;
-
- sto=(ComponentStorageHdl)NewHandleClear(sizeof(ComponentStorageRec));
-
- if (sto==(ComponentStorageHdl)0){
- res=((ComponentResult)MemError());
- } else {
-
- HLock((Handle)sto);
-
- // (*sto)->resFileRefNum=OpenComponentResFile((Component)self); // open the resource file
-
- (*sto)->self=(Component)self;
-
- // create default values for the syslog stuff
- (*sto)->ident[0]=0;
- (*sto)->refnum=0;
- (*sto)->logopts=0; // really ignored
- (*sto)->facility=LOG_USER; // random user messages
- (*sto)->mask=0xff; // mask nothing away
- (*sto)->specvalid=false;
- (*sto)->err=noErr;
-
- (*sto)->openCalled=false;
- (*sto)->slogopts=(*sto)->logopts;
- (*sto)->sfacility=(*sto)->facility;
- (*sto)->smask=(*sto)->mask;
- (*sto)->needSaved=false;
-
- // Set up the IU stuff
- (*sto)->i0h=(Intl0Hndl)IUGetIntl(0);
-
- if ((*sto)->i0h!=(Intl0Hndl)0){
- // detach it so we don't save the changes...
- DetachResource((Handle)(*sto)->i0h);
-
- // date as 01/01/95
- (*((*sto)->i0h))->shrtDateFmt|=dayLdingZ;
- (*((*sto)->i0h))->shrtDateFmt&=~century;
-
- // time as 15:06:30
- (*((*sto)->i0h))->timeCycle=0;
- (*((*sto)->i0h))->timeFmt|=secLeadingZ|minLeadingZ|hrLeadingZ;
- }
-
- /*
- Start with the default syslog spec. A file named 'syslog' will be created in the
- system folder. Use SetFile to change the spec to point somewhere else...
- */
- anErr=FindFolder(kOnSystemDisk,kSystemFolderType,kCreateFolder,&vref,&dirid);
- if (anErr==noErr){
- FInfo info;
-
- (*sto)->vRefNum=0;
- (*sto)->dirID=0L;
-
- anErr=FSMakeFSSpec(vref,dirid,"\psyslog",&((*sto)->spec));
-
- // (*sto)->spec.vRefNum=vref;
- // (*sto)->spec.parID=dirid;
-
- if ((anErr==noErr)||(anErr==fnfErr)){
- (*sto)->specvalid=true;
-
- (*sto)->vRefNum=vref;
- (*sto)->dirID=dirid;
-
- anErr=noErr;
- }
- }
-
- (*sto)->err=anErr;
-
- HUnlock((Handle)sto);
-
- SetComponentInstanceStorage(self,(Handle)sto);
- }
-
- return res;
- }
-
- pascal ComponentResult ComponentClose(Handle storage,ComponentInstance self){
- ComponentResult res=((ComponentResult)noErr);
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- DisposeHandle((Handle)(*sto)->i0h);
-
- HSetState(storage,s);
-
- DisposeHandle(storage);
-
- return res;
- }
-
- pascal ComponentResult ComponentCanDo(short selector){
- ComponentResult res=((ComponentResult)noErr);
-
- switch(selector){
- // Component Manager Routines
- case kComponentOpenSelect:
- case kComponentCloseSelect:
- case kComponentCanDoSelect:
- case kComponentVersionSelect:
- case kComponentTargetSelect:
- case kComponentRegisterSelect:
-
- // Add component specific routines here...
- case kopenlogSelector:
- case ksyslogSelector:
- case kcloselogSelector:
- case ksetlogmaskSelector:
- case kSetFileSelector:
- case kGetErrorSelector:
-
- res=((ComponentResult)1);
- break;
- default:
- res=((ComponentResult)0);
- break;
- }
-
- return res;
- }
-
- pascal ComponentResult ComponentVersion(void){
- ComponentResult res=((ComponentResult)kVersion);
-
- return res;
- }
-
- pascal ComponentResult ComponentTarget(Handle storage,ComponentInstance kidnapper){
- ComponentResult res=((ComponentResult)noErr);
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- (*sto)->kidnapper=kidnapper;
-
- HSetState(storage,s);
-
- return res;
- }
-
- pascal ComponentResult ComponentRegister(Handle storage){
- ComponentResult res=((ComponentResult)noErr);
- short refnum,oldref;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- oldref=CurResFile();
-
- refnum=OpenComponentResFile((*sto)->self);
-
- if (refnum>0){
- // use our resource file
- UseResFile(refnum);
-
- // show the icon
- ShowInitIcon(kIconID,true);
-
- // close our resource file
- CloseComponentResFile(refnum);
-
- // restore the old front resource
- UseResFile(oldref);
- } else {
- (*sto)->err=2005;
- }
-
- HSetState(storage,s);
-
- return res;
- }
-
- // Add component specific routines here or in another file
-
- /*
- ComponentOpenlog
-
- Handles the opening of the syslog file. Note that if we are opening an existing file, it's contents are
- purged.
- */
- pascal ComponentResult ComponentOpenlog(Handle storage,const char* ident,long logopt,short facility){
- ComponentResult res;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- // save the current stuff if necessary
- if (!((*sto)->openCalled)){
- // open called for the first time...
- if ((*sto)->needSaved){
- // the settings have changed, so we are not just resetting the syslog file
- (*sto)->openCalled=true;
- (*sto)->slogopts=(*sto)->logopts;
- (*sto)->sfacility=(*sto)->facility;
- (*sto)->smask=(*sto)->mask;
- }
- }
-
- if (Strlen((char*)ident)){
- // save the current ident string
- if (Strlen((char*)ident)>kMaxIdentLen){
- Strncpy((*sto)->ident,(char*)ident,kMaxIdentLen);
- } else {
- Strcpy((*sto)->ident,(char*)ident);
- }
- } else {
- (*sto)->ident[0]=0;
- }
-
- // save the logopts
- (*sto)->logopts=logopt;
-
- // save the facility
- if ((facility!=0)&&((facility&~LOG_FACMASK)==0))
- (*sto)->facility=facility;
-
- // purge the existing file if it exists
- if ((*sto)->specvalid){
- FInfo info;
-
- res=FSpGetFInfo(&((*sto)->spec),&info);
-
- if (res==noErr){
- // the file exists, get rid of it
- res=FSpDelete(&((*sto)->spec));
-
- if (res!=noErr){
- // file is busy or something, move it to the trash folder
- long dirid;
- short vref;
- FSSpec trash;
-
- // find the trash folder
- FindFolder(kOnSystemDisk,kTrashFolderType,kCreateFolder,&vref,&dirid);
-
- // make a spec for it
- FSMakeFSSpec(vref,dirid,(*sto)->spec.name,&trash);
-
- // allow the move to happen
- FSpCatMove(&((*sto)->spec),&trash);
- }
- }
- }
-
- (*sto)->err=(OSErr)res;
-
- HSetState(storage,s);
-
- return res;
- }
-
- pascal ComponentResult ComponentSyslog(Handle storage,short priority,const char* message){
- ComponentResult res=noErr;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
- Str255 msg;
- Str255 nstr;
- long ct;
- unsigned long time;
- OSErr anErr=noErr;
- char tempBuf[200];
-
- if (priority&~(LOG_PRIMASK|LOG_FACMASK)){
- libsprintf(tempBuf,"syslog: unknown facility/priority: %x",priority);
- ComponentSyslog(storage,LOG_ERR,tempBuf);
-
- priority&=LOG_PRIMASK|LOG_FACMASK;
- }
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- // if the priority clears the mask... Basically if the bit in the mask is set for this priority,
- // then we can continue (i.e. logging or notifying).
- if ( (!LOG_MASK(LOG_PRI(priority))) & ((*sto)->mask) ){
- anErr=noErr;
- goto ExitSyslog;
- }
-
- if ((priority&LOG_FACMASK)==0){
- // use the default facility
- priority|=(*sto)->facility;
- }
-
- nstr[0]=0;
-
- switch (priority&LOG_PRIMASK){
- case LOG_EMERG:
- ConcatPString(nstr,"\p<Emergency> ");
- break;
- case LOG_ALERT:
- ConcatPString(nstr,"\p<Alert> ");
- break;
- case LOG_CRIT:
- ConcatPString(nstr,"\p<Critical> ");
- break;
- case LOG_ERR:
- ConcatPString(nstr,"\p<Error> ");
- break;
- case LOG_WARNING:
- ConcatPString(nstr,"\p<Warning> ");
- break;
- case LOG_INFO:
- ConcatPString(nstr,"\p<Info> ");
- break;
- case LOG_DEBUG:
- ConcatPString(nstr,"\p<Debug> ");
- break;
- case LOG_NOTICE:
- ConcatPString(nstr,"\p<Notice> ");
- break;
- default:
- {
- // priority not in range, encode the number as a priority
- Str255 tstr;
- NumToString(priority,tstr);
-
- ConcatPString(nstr,"\p<");
- ConcatPString(nstr,tstr);
- ConcatPString(nstr,"\p> ");
- }
- break;
- }
-
- ReadDateTime(&time); // get time
-
- // build the date string
- IUDatePString(time,shortDate,msg,(Handle)(*sto)->i0h);
-
- // add it to the nstr
- ConcatPString(nstr,msg);
- ConcatPString(nstr,"\p ");
-
- // build the time string
- IUTimePString(time,true,msg,(Handle)(*sto)->i0h);
-
- // add it to the nstr
- ConcatPString(nstr,msg);
- ConcatPString(nstr,"\p ");
-
- // add the ident
- ct=Strlen((*sto)->ident);
- if (ct>0){
- BlockMoveData((*sto)->ident,&(nstr[nstr[0]+1]),ct);
- nstr[0]+=ct;
- ConcatPString(nstr,"\p ");
- } else {
- // use syslog:
- ConcatPString(nstr,"\psyslog");
- }
-
- // add the ': '
- ConcatPString(nstr,"\p: ");
-
- /*
- In normal syslog implementations, a connection is opened with the syslog daemon
- and the string is passed to the syslog daemon for logging (and the console if the flag is
- set). The connection is usually an AF_UNIX connection, or local system connection.
-
- In this component, we open a file, add the message, then close the file. Close enough to
- a local system connection for me ;-)
-
- Barring any crashes while the file is open, this will ensure that the file is updated and
- closed so no messages are lost.
-
- This also means that when I write a syslog daemon that I can have the daemon open a file
- and write this information into it just as easily.
- */
-
- // add the message to the log file
- if ((*sto)->specvalid){
- // open the file
- anErr=FSpOpenDF(&((*sto)->spec),fsRdWrPerm,&((*sto)->refnum));
-
- // move to the end of the file if it's open
- if (anErr==noErr)
- SetFPos((*sto)->refnum,fsFromLEOF,0L);
- else {
- (*sto)->refnum=0;
-
- // problem opening the file, try to create it...
- anErr=FSpCreate(&((*sto)->spec),kSyslogCreator,'TEXT',smSystemScript);
-
- if (anErr==noErr){
- // if the file was just created, then we don't need to seek, just open
- anErr=FSpOpenDF(&((*sto)->spec),fsRdWrPerm,&((*sto)->refnum));
- if (anErr!=noErr)
- (*sto)->refnum=0;
- } else {
- // DebugNotify("\pLog component: Error creating the file!");
- }
- }
-
- if ((anErr==noErr)&&((*sto)->refnum!=0)){
- // OK to write to the file, add the nstr first
- ct=(long)(nstr[0]);
- FSWrite((*sto)->refnum,&ct,&(nstr[1]));
-
- // add the message to the file
- ct=(long)Strlen((char*)message);
- FSWrite((*sto)->refnum,&ct,message);
-
- // now add a newline char
- msg[1]=0x0d;
- ct=1;
- FSWrite((*sto)->refnum,&ct,&(msg[1]));
-
- // done, flush & close file
- FSClose((*sto)->refnum);
- (*sto)->refnum=0;
- FlushVol((StringPtr)0,(*sto)->spec.vRefNum);
- }
- } else {
- anErr=2002; // fsspec is invalid
- }
-
- ExitSyslog:
- (*sto)->err=anErr;
-
- HSetState(storage,s);
-
- return res;
- }
-
- pascal ComponentResult ComponentCloselog(Handle storage){
- ComponentResult res=noErr;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- // the current log should be closed and the old syslog reused.
-
- if ((*sto)->openCalled){
- // open was called and the settings were changed
- // restore the settings to the default values.
-
- (*sto)->openCalled=false;
- (*sto)->facility=(*sto)->sfacility;
- (*sto)->mask=(*sto)->smask;
- (*sto)->logopts=(*sto)->slogopts;
- (*sto)->needSaved=false;
- (*sto)->ident[0]=0;
-
- if (((*sto)->vRefNum!=0)&&((*sto)->dirID!=0L)){
- FSMakeFSSpec((*sto)->vRefNum,(*sto)->dirID,"\psyslog",&((*sto)->spec));
- (*sto)->specvalid=true;
- } else {
- (*sto)->specvalid=false;
- }
- }
-
- HSetState(storage,s);
-
- return res;
- }
-
- pascal ComponentResult ComponentSetlogmask(Handle storage,short maskpri){
- ComponentResult res;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- res=(ComponentResult)(*sto)->mask;
-
- // save the new mask
- if (maskpri!=0)
- (*sto)->mask=maskpri;
- (*sto)->needSaved=true;
-
- HSetState(storage,s);
-
- return res;
- }
-
- pascal ComponentResult ComponentSetFile(Handle storage,FSSpecPtr spec){
- ComponentResult res;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
- Boolean didClose=false;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- (*sto)->specvalid=false;
-
- // save the fsspec stuff
- res=FSMakeFSSpec(spec->vRefNum,spec->parID,spec->name,&((*sto)->spec));
-
- if ((res==noErr)||(res==fnfErr)){
- (*sto)->specvalid=true;
- (*sto)->needSaved=true;
- }
-
- HSetState(storage,s);
-
- return res;
- }
-
- pascal ComponentResult ComponentGetError(Handle storage,OSErr* err){
- ComponentResult res=noErr;
- SignedByte s=HGetState(storage);
- ComponentStorageHdl sto;
-
- HLock(storage);
- sto=(ComponentStorageHdl)storage;
-
- *err=(*sto)->err;
- (*sto)->err=noErr;
-
- HSetState(storage,s);
-
- return res;
- }
-
- /*
- In PPC applications, constructors and destructors for global and static objects are called automatically
- by __cplusstart, which is actually the main entry point to your application (and not main()). This
- routine calls your constructors, initializes your QuickDraw globals, calls your main() function, then
- calls your destructors.
-
- In a shared library, constructors for global and static objects are called by __cplusinit, which the linker
- assigns as an initialization routine. The Code Fragment Manager will automatically call this initialization
- routine when your shared library is loaded. __cplusinit will also allow hook your shared library's
- QuickDraw globals to the QuickDraw globals of the calling application. Destructors for global and static
- objects are called by __cplusterm, which the linker assigns as a termination routine. The Code Fragment
- Manager will automatically call this termination routine when your shared library is unloaded.
-
- In code resources, there is no way to call these constructors or destructors automatically, or hook
- QuickDraw globals, and still preserve the arguments passed to your main entry point (main()). Instead,
- you will need to call initialization and termination routines to do this for you.
-
- In C, you should use __rsrcinit() and __rsrcterm(), defined in stdlib.h.
-
- In C++, you should use __cplusrsrcinit() and __cplusrsrcterm(), defined in new.h.
-
- The C++ initialization and termination routines will automatically call the C initialization and termination
- routines. You should only use one set or the other.
-
- You must not use any objects that rely on their constructor, or any QuickDraw globals, before calling
- __rsrcinit() or __cplusrsrcinit().
-
-
- Singlely-entrant code resources :
-
- If your code resource is called only once, you should call __rsrcinit() or __cplusrsrcinit() at the start of
- main(), and __rsrcterm() or __cplusrsrcterm() at the end.
-
- Reentrant code resources :
-
- If your code resource is reentrant, you will need to call __rsrcinit() or __cplusrsrcinit() only the first
- time through, and __rsrcterm() or __cplusrsrcterm() the last time through.
-
-
- Colen Garoutte-Carson
- Symantec Corp.
- */
-
-
-
-